package jsmc.opendata.nantes.util;

import jsmc.android.utils.DataBaseHelper;
import jsmc.moteurcsv.MoteurCsv;
import jsmc.moteurcsv.modele.InsertObject;
import jsmc.opendata.nantes.modele.Equipement;
import jsmc.opendata.nantes.modele.Parking;
import jsmc.opendata.pratikanant.Constants;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;

import android.content.Context;
import android.database.Cursor;
import android.util.Log;

/**
 * Manager des équipements.
 */
public class EquipementManager {

	/**
	 * Logger.
	 */
	private static final Logger LOGGER = Logger.getLogger(EquipementManager.class.getSimpleName());

	/**
	 * Instance du singletton.
	 */
	private static EquipementManager instance;

	/**
	 * Fichier a chargé qui contient les données de Nantes Métropole sous licence Open Database License (ODbL).
	 * <a href="http://data.nantes.fr/donnees/detail/?tx_icsoddatastore_pi1[page]=1&tx_icsoddatastore_pi1[uid]=45">Telechargement</a>
	 */
	private static final String EQUIPEMENTS_PUBLICS_DEPLACEMENT_CSV = "/assets/Equipements_publics_deplacement.csv";

	/**
	 * Encoding du fichier fournis par Nantes Métropole.
	 */
	//private static final String CHARSET_NAME = "ISO-8859-15";
	private static final String CHARSET_NAME = "UTF-8";

	/**
	 * Utilsation de la base ou du fichier csv
	 */
	private boolean use_db = false;

	private Context mcontext;


	/**
	 * @return l'instance du singletton.
	 */
	public static synchronized EquipementManager getInstance() {
		if (instance == null) {
			instance = new EquipementManager();
		}
		return instance;
	}

	/**
	 * Défini si on utilise la bese ou bien le csv
	 */
	public void UseDb(Context context) {
		this.use_db = true;
		this.mcontext = context;
	}

	/**
	 * Méthode permettant de completter les parkings.
	 *
	 * @param parkings les parkings à compléter.
	 * @param use_db 
	 */
	public void completeParkings(List<Parking> parkings) {
		for (Parking parking : parkings) {
			NeoLog.v("jsmc","Complete parking nom:"+parking.getNom()+" IdObj:"+parking.getIdObj());
			completeParking(parking);
		}
	}

	/**
	 * Méthode permettant de completer un parking.
	 *
	 * @param parking parking à completer.
	 * @param use_db 
	 */
	private void completeParking(Parking parking) {
		NeoLog.v("EquipementManager","completeParking " + parking.getIdentifiant()+" / "+parking.getIdObj());

		Equipement equipement = getMapEquipements().get(parking.getIdObj());

		if (equipement == null) {

			LOGGER.warning("Pas d'equipements trouvés pour le parking " + parking.getIdentifiant()+" / "+parking.getIdObj());

		} else {

			//parking.setNom(equipement.getNom());
			parking.setLatitude(equipement.getLatitude());
			parking.setLongitude(equipement.getLongitude());

		}
	}

	/**
	 * Map des equipements.
	 */
	private Map<Integer, Equipement> mapEquipements;

	/**
	 * @return {@link EquipementManager#mapEquipements}.
	 */

	public Map<Integer, Equipement> getMapEquipements() {
		if (mapEquipements == null) {
			mapEquipements = new HashMap<Integer, Equipement>();

			if(use_db){
					
				EquipementDB eq = new EquipementDB(mcontext,Arrays.<Class<?>>asList(Equipement.class));
				mapEquipements = eq.GetEquipement(10);
				eq.queryDbAndInsert(Equipement.class,
						new EquipementInsertObject(mapEquipements));

			} else {

				MoteurCsv moteurCsv = new MoteurCsv(Arrays.<Class<?>>asList(Equipement.class));
				BufferedReader bufferedReader = null;
				try {

					bufferedReader = new BufferedReader(new InputStreamReader(
							EquipementManager.class.getResourceAsStream(EQUIPEMENTS_PUBLICS_DEPLACEMENT_CSV), CHARSET_NAME));

					try {
						/* necessaire pour supprimer le BOM s'il existe */
						bufferedReader.skip(0);
						NeoLog.v("EquipementManager","getMapEquipements parseFileAndInsert");

						moteurCsv.parseFileAndInsert(bufferedReader, 
								Equipement.class,
								new EquipementInsertObject(mapEquipements));

						NeoLog.v("EquipementManager","getMapEquipements parseFileAndInsert fini");

					} catch (IOException e) {
						LOGGER.warning(e.getMessage());

					} finally {
						try {
							bufferedReader.close();
						} catch (Exception exception) {
							LOGGER.warning(exception.getMessage());
						}
					}
				} catch (UnsupportedEncodingException exception) {
					NeoLog.v("EquipementManager","getMapEquipements BufferedReader error");

					LOGGER.warning(exception.getMessage());
				}

			}

		}

		NeoLog.v("EquipementManager","getMapEquipements :"+mapEquipements.size()+" "+mapEquipements.containsKey("idObj"));
		return mapEquipements;
	}
	/**
	 * Gestion des {@link Equipement}.
	 */
	private static final class EquipementInsertObject implements InsertObject<Equipement> {
		/**
		 * Map des equipements.
		 */
		private Map<Integer, Equipement> mapEquipements;

		/**
		 * Constructeur.
		 *
		 * @param mapEquipements map des équipements.
		 */
		private EquipementInsertObject(Map<Integer, Equipement> mapEquipements) {
			this.mapEquipements = mapEquipements;
		}

		public void insertObject(Equipement objet) {
			//NeoLog.v("EquipementInsertObject","insertObject "+objet.getIdObj()+" "+objet.getNom());
			mapEquipements.put(objet.getIdObj(), objet);
		}
	}
}
